--[[
百家乐游戏规则
游戏使用一副除去大小王的扑克牌，共4个花色52张牌。


]]

local math_random = math.random
local table_copy = table.copy
local table_remove = table.remove
local table_mix = table.mix
local table_insert = table.insert
local string_split = string.split

local Rule = class("Rule")

function  Rule:ctor()
	--随机种子
	math.randomseed(os.time())

	-- -- 牌的类型
	-- CARD_SUIT = {
	-- 	NONE = 0,	--大小王 ■
	-- 	CLUB =	1,  -- 梅 ♣
	-- 	DIAMOND = 2,  -- 方 ♦
	-- 	HEART =	3,  -- 红 ♥
	-- 	SPADE =	4,  -- 黑 ♠
	-- }
	-- -- 面值特征字符 （X ：10 V ：小王 W ：大王）
	-- CARD_RANK_CHAR = { 'A','2', '3', '4', '5', '6', '7', '8', '9', 'X', 'J', 'Q', 'K', 'V', 'W'}
	--扑克牌说明
	self.card = {
		101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113,   --♣
     	201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213,   --♦
     	301, 302, 303, 304, 305, 306, 307, 308, 309, 310, 311, 312, 313,   --♥
     	401, 402, 403, 404, 405, 406, 407, 408, 409, 410, 411, 412, 413,   --♠
	}

	--池位置
	self.pool_name = {
		player = 1,
		tie = 2,
		banker = 3,
		player_pairs = 4,
		banker_pairs = 5,
	}	
	--要发的牌
	self.cards = {}
	self.card_pair = 1	--有几副牌
	self.config_cards = nil --是否有配置牌

	--和牌
	self.tie_cards = {
	 	{{213,101,309,},{403,408,209,}},
	 	{{106,110,},{313,306,}},
	 	{{411,406,},{102,204,}},
	 	{{105,108,212,},{402,401,412,}},
	 	{{205,202,},{302,301,404,}},
	 	{{112,207,},{307,311,}},
	 	{{203,103,},{206,410,}},
	 	{{113,109,},{304,405,}},
	 	{{305,303,},{208,413,}},
	 	{{107,308,210,},{201,310,104,}},

	 	{{405,411,110,},{312,203,202,}},
	 	{{310,308,},{408,112,}},
		{{406,201},{105,402}},
		{{303,309,305},{109,108}},
		{{207,211},{312,407}},
		{{411,202,213},{212,112,102}},
		{{403,405},{313,408}},
		{{103,204},{307,310}},
		{{306,413},{104,302}},
		{{205,208,304},{113,107}},

		{{101,308},{410,209}},
		{{409,106,401},{206,210,111}},
		{{301,203,110},{412,404,311}},
		{{411,310,211},{312,210,413}},
		{{307,409},{204,402}},
		{{404,113,306},{401,212,109}},
		{{207,308,410},{412,105,112}},
		{{311,309},{101,208}},
		{{304,305},{403,206}},
		{{303,407,107},{202,103,102}},
		{{108,408},{104,302}},
		{{209,201,406},{301,205,110}},		

		{{410,305,201},{108,103,205}},
		{{408,208},{406,413}},
		{{101,209,304},{105,206,203}},
		{{309,402,310},{401,210,111}},
		{{109,312},{106,403}},
		{{107,113},{307,212}},
		{{306,104,202},{302,411,110}},
		{{308,409},{407,311}},
		{{303,313,301},{112,404,213}},
		{{405,207,102},{412,204,211}},
		{{203,410,302},{109,105,101}},
		{{404,110,208},{111,102,411}},
		{{112,407},{409,205,303}},
		{{412,402,213},{311,210,202}},
		{{408,304,201},{108,305,413}},
		{{401,405},{406,211}},
		{{313,106},{306,310}},
		{{403,206},{113,209}},
		{{309,103,212},{107,204,301}},					 	
	}		

	--对子牌
	self.play_pair_cards = {
		--闲赢
		{{202,402,212},{303,308,111}},
		{{209,109},{405,305}},
		{{301,201,206},{311,106}},
		{{113,413,104},{110,105,207}},
		{{108,208},{112,211,103}},
		{{304,404},{107,406}},
		{{401,101,309},{403,210,407}},
		{{102,302,408},{213,310,412}},				
		{{109,309},{404,408}},
		{{210,310,208},{112,205}},
		{{204,304},{311,106}},
		{{108,308},{302,113,413}},
		{{401,201,101},{411,403,409}},
		{{312,412,407},{410,213,313}},
		{{406,206,207},{105,405,111}},
		{{102,402,203},{209,306,212}},
		{{303,103},{104,211,110}},
		{{107,307,305},{301,202}},
	}
	self.bank_pair_cards = {
		--庄赢
		{{403,102,409},{401,201,204}},
		{{212,205,110},{107,307,104}},
		{{406,412},{106,306,405}},
		{{113,304,206},{303,103}},
		{{213,111,313},{208,408}},
		{{109,302,210},{308,108}},
		{{309,305,202},{407,207,404}},
		{{312,211,105},{310,410,209}},
		{{311,112,203},{101,301,402}},	
		{{313,307},{113,413,309}},
		{{110,302,308},{106,306,409}},
		{{312,111,112},{411,211,201}},
		{{107,404,203},{305,405,105}},
		{{410,202,412},{407,207,304}},
		{{204,310,206},{303,403}},
		{{402,205},{209,109}},
		{{104,213,210},{408,208}},
		{{108,103,311},{301,401,212}},
		{{212,302,201},{313,413,208}},
		{{410,401,110},{405,205,203}},
		{{308,408},{204,404}},
		{{111,104,206},{412,112,306}},
		{{304,407,403},{207,107,102}},
		{{210,113},{209,309}},
		{{310,301,101},{211,311,106}},
		{{312,202},{109,409}},
		{{305,411,105},{103,303}},					
	}
	self.tie_pair_cards = {
		--和赢
		--庄对
		{{102,406},{409,209}},
		{{310,306},{403,103}},
		{{201,313,112},{212,412,301}},
		{{309,407},{208,308}},
		{{110,213,202},{311,411,402}},
		{{207,108,205},{105,305,111}},
		{{204,109,408},{410,210,101}},
		{{302,106},{104,404}},
		{{304,413,211},{307,107,312}},
		{{401,405},{203,303}},	
		
		--闲对
		{{301,201,211},{308,404,313}},
		{{103,403},{101,401,104}},
		{{202,102,306},{111,312,110}},
		{{307,407,309},{406,209,208}},
		{{303,203},{210,206}},
		{{412,212,207},{304,408,405}},
		{{409,109},{106,302}},
		{{213,113,105},{305,112,410}},
		{{411,311,402},{204,108,310}},	
		{{311,211,103},{411,203,210}},
		{{212,112,207},{301,206}},
		{{309,209},{108,313}},
		{{201,101,408},{310,110,111}},
		{{404,104},{410,308}},
		{{302,102,403},{407,113}},
		{{205,405,402},{303,109,412}},
		{{307,107,401},{409,106,312}},
		{{204,304},{213,208}},
		{{406,306,305},{105,202}},				
	}

end

--洗牌
function Rule:shuffle()	
	self.cards = {}
	for i = 1, self.card_pair do 
		for _, v in pairs(self.card) do 
			table_insert(self.cards, v)
		end
	end	
	table_mix(self.cards)

end


--取闲，庄牌，补牌
function Rule:getPlayAndBankCards(cards)	
	local play_cards = {} --闲牌
	local bank_cards = {} --庄牌
	if not cards then 
		cards = self.cards
	end
	--闲庄先各发两张牌
	for k=1, 4 do
		if k < 3 then
			table_insert(play_cards, table_remove(cards, 1))			
		else
			table_insert(bank_cards, table_remove(cards, 1))
		end	
	end
	local play_point = self:getPoint(play_cards)
	local bank_point = self:getPoint(bank_cards)
	--8,9点都不补牌
	if play_point == 8 or play_point == 9 or bank_point == 8 or bank_point == 9 then 
		return play_cards, bank_cards
	end

	--闲	小于5点补牌
	if play_point <= 5 then
		table_insert(play_cards, table_remove(cards, 1))
		play_point = self:getPoint(play_cards)
	end

	--庄补牌
	local bank_point = self:getPoint(bank_cards)
	if bank_point < 3 then
		table_insert(bank_cards, table_remove(cards, 1))
		return play_cards, bank_cards 
	elseif bank_point == 3 then
		if #play_cards == 3 and play_point == 8 then
			return play_cards, bank_cards 
		else
			table_insert(bank_cards, table_remove(cards, 1))
			return play_cards, bank_cards 
		end
	elseif bank_point == 4 then
		if #play_cards == 3 and (play_point == 1 or play_point == 8 or play_point == 9 or play_point == 0) then
			return play_cards, bank_cards 
		else
			table_insert(bank_cards, table_remove(cards, 1))
			return play_cards, bank_cards 
		end
	elseif bank_point == 5 then
		if #play_cards == 3 and (play_point == 1 or play_point == 8 or play_point == 9 or play_point == 0) then
			return play_cards, bank_cards 
		else
			table_insert(bank_cards, table_remove(cards, 1))
			return play_cards, bank_cards 
		end
	elseif bank_point == 6 then
		if #play_cards == 3 and (play_point == 6 or play_point == 7) then
			table_insert(bank_cards, table_remove(cards, 1))
			return play_cards, bank_cards 			
		else
			return play_cards, bank_cards 
		end
	elseif bank_point == 7 then
		return play_cards, bank_cards 
	end

	print("-------->取牌出错：", "play_cards:", play_cards, "bank_cards:", bank_cards)
	return play_cards, bank_cards
end

--取剩余每张牌的数量
function Rule:getEachCardLeftNum()
	local tb = {}
	for _, u in ipairs(self.card) do
		tb[u] = 0
	end

	for k, v in pairs(self.cards) do
		tb[v] = (tb[v] or 0) + 1
	end
	return tb
end

--是否有对子 
function Rule:existPair(cards)
	if #cards < 2 then 
		return false
	end
	for k=1, 2 do 
		for j=k+1, 2 do 
			if cards[k]%100 == cards[j]%100 then
				return true
			end
		end
	end
	return false
end

--获取点数
function Rule:getPoint(cards)
	local point = 0
	for k, v in ipairs(cards) do
		local temp = v%100
		if temp < 10 then --大于10 为0点
			point = temp + point
		end		
	end
	point = point % 10
	return point
end

--比牌， cards1闲牌， cards2庄牌
function Rule:compareCard(cards1, cards2)
	local point1 = self:getPoint(cards1)
	local point2 = self:getPoint(cards2)
	if point1 > point2 then
		return 1 --闲赢
	elseif point1 < point2 then
		return 3 --庄赢
	else
		return 2 --和
	end
end

--[[
取想要的结果
card_res:闲赢:Rule.wantCardTag.PLAY_WIN; 庄赢: Rule.wantCardTag.BANK_WIN,和:Rule.wantCardTag.TIE；
no_play_pair：为true时闲不出现对子
no_bank_pair：为true时庄不出现对子
]]--
function Rule:getWantCard(card_res, no_play_pair, no_bank_pair)
	local play, bank = {}, {}
	if not card_res and not no_play_pair and not no_bank_pair then --都不需要对子条件
		return self:getPlayAndBankCards()
	end

	local try_num = 100 --尝试取牌的次数
	if #self.cards > 100 then
		try_num = 500
	end
	if card_res == self.pool_name.tie or no_play_pair == true or no_bank_pair == true then
		try_num = try_num + 200
	end

	for n = 1, try_num do
		local play_card, bank_card = self:getPlayAndBankCards()
		local compare_res = self:compareCard(play_card, bank_card)
		local is_play_pair = self:existPair(play_card)
		local is_bank_pair = self:existPair(bank_card)

		if (not no_play_pair and not no_bank_pair) or --都没有对子要求
			(no_play_pair and not is_play_pair and ((no_bank_pair and not is_bank_pair) or (not no_bank_pair)) ) or --闲没有对子要求		    
			(no_bank_pair and not is_bank_pair and not is_play_pair) then --庄没有对子要求

			play, bank = play_card, bank_card --符合对子条件的
			if card_res == self.pool_name.player and compare_res == 1 then
				return play_card, bank_card, true
			elseif card_res == self.pool_name.banker and compare_res == 3 then				
				return play_card, bank_card, true
			elseif card_res == self.pool_name.tie and compare_res == 2 then
				return play_card, bank_card, true
			end			
		end
		for _,v in ipairs(bank_card) do
			table_insert(self.cards, v)
		end
		for _,v in ipairs(play_card) do
			table_insert(self.cards, v)
		end
		table_mix(self.cards)
	end

	for i=1, (#play + #bank) do 
		for j=#self.cards, 1, -1 do 
			table_remove(self.cards, j)
		end
	end

	--如果没找到符合条件的
	if not next(play) or not next(bank) then
		errlog("没找到符合条件的牌not find........")
	 	-- play, bank = self:getPlayAndBankCards()
	 	return play, bank, false
	end	
	return play, bank, true
end


--根据位置开出想要的结果的牌
--pool_id要开的位置
--要闲赢， 但牌是庄赢 可以把庄的牌换给闲，但要注意是两边牌数相等的情况才可以， 因为百家乐是闲先补牌
--
function Rule:getWantCard2(pool_id)	
	local play_card, bank_card = self:getPlayAndBankCards()
	local compare_res = self:compareCard(play_card, bank_card)
	local is_play_pair = self:existPair(play_card)
	local is_bank_pair = self:existPair(bank_card)
	if compare_res == pool_id then 
		return play_card, bank_card
	end	
	if pool_id == self.pool_name.player or pool_id == self.pool_name.banker then 	
		while compare_res == self.pool_name.tie do 
			for _,v in ipairs(bank_card) do
				table_insert(self.cards, v)
			end
			for _,v in ipairs(play_card) do
				table_insert(self.cards, v)
			end
			table_mix(self.cards)			
			play_card, bank_card = self:getPlayAndBankCards()
			compare_res = self:compareCard(play_card, bank_card)
		end		
	end
	if compare_res == pool_id then 
		return play_card, bank_card
	end		
	if pool_id == self.pool_name.tie then 
		local cards = self.tie_cards[math_random(1,#self.tie_cards)]
		play_card = cards[1]
		bank_card = cards[2]
		return play_card, bank_card
	end
	dbglog("__________牌不符合系统需要_________", pool_id, compare_res,  play_card, (bank_card))
	local tag_time = os.time()
	dbglog("___开始再取牌_____", tag_time)
	play_card, bank_card = self:getWantCard(pool_id)	
	dbglog("___结束再取牌_____", os.time() - tag_time, (play_card), (bank_card))

	return play_card, bank_card 
end

--取想要的对子牌
function Rule:getPairCards(pool_id)
	local play_card = nil
	local bank_card = nil
	local cards = {}
	if pool_id == self.pool_name.player then 
		cards = self.play_pair_cards[math_random(1, #self.play_pair_cards)]
	elseif pool_id == self.pool_name.banker then 
		cards = self.bank_pair_cards[math_random(1, #self.bank_pair_cards)]
	elseif pool_id == self.pool_name.tie then 
		cards = self.tie_pair_cards[math_random(1, #self.tie_pair_cards)]
	else
		cards = self.play_pair_cards[math_random(1, #self.play_pair_cards)]
	end
	-- dbglog("___cards___",pool_id, (cards))
	play_card = cards[1]
	bank_card = cards[2]
	return play_card, bank_card
end

function Rule:getCards()
	if self.config_cards then 
		--有配置牌
		return self.config_cards[1], self.config_cards[2]
	end
	return self.rule:getPlayAndBankCards()
end

--配置牌
function Rule:configCards(uid, msg)
	print("______configCards______", uid, (msg))
	if msg.close == 0 then 
		self.config_cards = nil
		return 
	end
	local function setCards(cards)
		for k, v in pairs(cards) do 
			cards[k] = tonumber(cards[k])
		end
	end
	local cards1 = string_split(msg.cards1, ".")
	local cards2 = string_split(msg.cards2, ".")
	setCards(cards1)
	setCards(cards2)
	self.config_cards = {
		cards1,
		cards2,
	}

	errlog("_config_cards_________", (self.config_cards))
	return true
end

--清空牌
function Rule:clearCard()
	self.cards = {}
end

--是否有配置牌
function Rule:isPeiPai()
	return self.config_cards
end


return Rule